iT邦幫忙

2022 iThome 鐵人賽

DAY 8
0
自我挑戰組

菜鳥前端修練之旅系列 第 8

Day 08 | 傳值與傳址

  • 分享至 

  • xImage
  •  

JavaScript 中,值的傳遞行為分成兩種:「傳值與傳址」,決定這兩種傳遞方式的就是「型別」。

基本型別用傳值、物件型別用傳址。

傳值 | Pass by value

基本型別用傳值,所以先來看看基本型別有哪些:

  • string
  • number
  • boolean
  • null
  • undefined

當值為基本型別時,賦值是使用複製的方式,也就是只拷貝它的值。

const a = 1;
const b = a;

console.log(a === b); // true

上面的 === 是比較兩個值是否相等。這種純粹只是複製值的方式、且不影響到到對方的行為,稱為 傳值

所以當我們修改其中一邊:

const a = 1;
let b = a;
b = 2

console.log(a); // 1
console.log(a === b); // false

另一個是不影響的。

傳址 | Pass by reference

物件型別就不一樣了,當我們賦值時,會引用該地址來指向物件。

const obj = { a: 1 };
const obj2 = { a: 1 };

console.log(obj === obj2); //false

雖然兩個 obj 的值相同,但物件的比較是看記憶體位置是否相同,所以為 false

因為記憶體位置相同,所以當我們嘗試修改其中一個物件時:

const obj = { a: 1 };
const obj2 = obj;
obj2.a = 2

console.log(obj.a); // 2
console.log(obj2.a); // 2

兩個 obja 都變成了 2。

透過函式

如果物件在函式中被重新賦值,那外部物件則不影響。

const person = { name: 'Peter' };

function changeName(obj){
    obj = { name: 'Tim' }
}

changeName(person)
console.log(person) // { name: 'Peter' }

如果不是重新賦值,則變成傳址。

const person = { name: 'Peter' };

function changeName(obj){
    obj.name = 'Tim'
}

changeName(person)
console.log(person) // { name: 'Tim' }

深拷貝與淺拷貝

除了傳值傳址外,我們也常常會聽到淺拷貝(Shallow copy)與深拷貝(Deep copy)兩個詞,其實我們已經知道淺拷貝是什麼了,就是上面文章提到的傳址,只會參考同一個物件。

那如果我想要複製一個全新的物件勒? 這時候就需要深拷貝。

深拷貝(Deep copy)

我們可以透過 JSON.stringifyJSON.parse 建立出新的物件。

const obj1 = {
  name: 'Peter',
  age: 18
}

const obj2  = JSON.parse(JSON.stringify(obj1))
obj2.name = 'Tim' // 修改 obj2
console.log(obj1.name) // obj1 不會跟著變,印出 Peter

最後再補充一下定義:

  • 淺拷貝:只複製第一層,第二層還是保有參考的特性。
  • 深拷貝:複製全新物件,兩者指向不同記憶體。

參考資料


上一篇
Day 07 | 事件冒泡與捕獲
下一篇
Day 09 | Cookie、LocalStorage 與 SessionStorage
系列文
菜鳥前端修練之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言